/*
 * slice 是一类引用，所以它没有所有权；
 * string slice 是 String 中一部分值的引用；
 * 使用[start_index..end_index]指定range来创建一个新的slice，range规则是，前开后闭；
 * 即，从start_index开始，但不包含start_index，至end_index结束，但包含end_index；
 * slice 中存储的数据有：指向原始数据索引的指针、开始位置以及长度
 */

fn main() {
    let s = String::from("hello world");
    let ref_s = &s;
    println!("{}\n{}\n", ref_s, "12345678910");
    let hello = &s[0..5];
    let world = &s[6..11];
    println!("{}, {}", hello, world);

    // range语法
    // 省略写法1
    println!("省略开头的0, 直接从..开始");
    let s = String::from("hello world");
    let slice1 = &s[0..2];
    let slice2 = &s[..2];
    println!("{}, {}", slice1, slice2);

    // 省略写法2
    println!("省略结尾索引 直接以..结束");
    let len = s.len();
    let slice1 = &s[3..len];
    let slice2 = &s[3..];
    println!("{}, {}", slice1, slice2);

    // 省略写法3
    println!("省略开始和结束索引，只有.., 表示获取原始数据的全部");
    let slice1 = &s[0..len];
    let slice2 = &s[..];
    println!("{}, {}", slice1, slice2);

    // 多字节字符，无法创建中间位置的slice，程序将会因错误而退出
    let s = String::from("你好，世界");
    // byte index 2 is not a char boundary; it is inside '你' (bytes 0..3)
    // let slice1 = &s[0..2];
    // 一个中文字符占三个字节，所以数学的范围是(0, 3]，切片为[0..3]
    let slice1 = &s[0..3];
    println!("{}", slice1);
    // 你 好 ，世  界
    // 3  6 9 12 15
    let slice2 = &s[6..]; // 6正好是‘好’结束，后面就是‘，世界’
    println!("{}", slice2);
}
